#! /usr/bin/python
import socket
import sys
import os
import re
import backupManager.config as config
from backupManager.enum import AEnums
import math
import datetime
import Pyro.core
import hashlib
import traceback

host = ''
port = config.pyro_port
backlog = 5
buffer_size = 8192
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)

class indexServer(Pyro.core.ObjBase):
	def __init__(self):
		Pyro.core.ObjBase.__init__(self)

	def index(self,commDict):
		return indexDrive(commDict)

def indexDrive(commDict):
	print 'Received index request',str(datetime.datetime.now()),commDict
	if not os.path.exists(commDict[AEnums.REMOTEPATH]):
		return AEnums.NOTEXIST
	if commDict[AEnums.VALIDEXTS]:
		validext = '|'.join(commDict[AEnums.VALIDEXTS])
		validext = "\.(" + validext + ")$"
	else:
		validext = None
	if commDict[AEnums.SKIPLIST]:
		skip = '|'.join(commDict[AEnums.SKIPLIST])
		skip = re.compile(skip,re.IGNORECASE)
	else:
		skip = None
	try:
		root = []
		files = []
		if len(commDict[AEnums.PATHS]) > 1 or (len(commDict[AEnums.PATHS]) == 1 and commDict[AEnums.PATHS][0] != commDict[AEnums.SEP]):
			for path in commDict[AEnums.PATHS]:
				path = path.replace(commDict[AEnums.SEP],os.sep)
				path = unicode(path)
				newFile = index(path,validext,skip,files,root=True,commDict=commDict)
				root.append(newFile[AEnums.ID])
		else:
			result = index(unicode(os.sep),validext,skip,files,root=True,commDict=commDict)
			root.append(result[AEnums.ID])
	except:
		exc_type, exc_value, exc_traceback = sys.exc_info()
		traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout)
		result = None
	print 'Done indexing!',str(datetime.datetime.now())
	return {
		AEnums.FILES : files,
		AEnums.ROOT : root,
	}

def index(path,validext,skip,filesIn,root=False,commDict=None):
	dir = commDict[AEnums.REMOTEPATH] + os.sep + path
	while re.search(r'/$',dir,re.IGNORECASE):
		dir = re.sub(r'/$','',dir)
	if not os.path.isdir(dir):
		return None
	try:
		files = os.listdir(unicode(dir))
	except:
		raise
		return None
	fd = {
		AEnums.NAME : os.path.basename(dir),
		AEnums.PATH : os.path.dirname(os.path.join(commDict[AEnums.REMOTEPATH],path)).replace(commDict[AEnums.REMOTEPATH],'').replace(os.sep,commDict[AEnums.SEP]),
		AEnums.PREFIX : commDict[AEnums.NAME]+':',
		AEnums.DIR : True,
		AEnums.VOLNAME : commDict[AEnums.NAME],
		AEnums.SERIAL : commDict[AEnums.SERIAL],
		AEnums.SIZE : '0',
		AEnums.MTIME : '0',
        AEnums.PARENT : '',
        AEnums.SETNAME : commDict[AEnums.SETNAME],
	}
	m = hashlib.md5()
	m.update(fd[AEnums.NAME].encode('UTF-16'))
	m.update(fd[AEnums.PATH].encode('UTF-16'))
	m.update(fd[AEnums.VOLNAME])
	m.update(fd[AEnums.SERIAL])
	id = m.hexdigest()
	fd[AEnums.ID] = id
	passedFiles = []
	if validext:
		ext = re.compile(validext,re.IGNORECASE)
	else:
		ext = None
	for foundFile in files[:]:
		if not os.access(os.path.join(dir,foundFile),os.R_OK):
			continue
		if skip:
			if re.search(skip,foundFile):
				continue
		if not os.path.isdir(os.path.join(dir,foundFile)):
			if ext:
				if not re.search(ext,foundFile):
					continue
		newFile = None
		if os.path.isdir(os.path.join(dir,foundFile)):
			newFile = index(os.path.join(path,foundFile),validext,skip,filesIn,False,commDict)
		else:
			mtime = int(math.floor(os.path.getmtime(os.path.join(dir,foundFile))))
			if mtime%2:
				mtime += 1
			newFile = {
				AEnums.NAME : foundFile,
				AEnums.PATH : path.replace(os.sep,commDict[AEnums.SEP]),
				AEnums.PREFIX : commDict[AEnums.NAME]+':',
				AEnums.DIR : False,
				AEnums.SIZE : float(os.path.getsize(os.path.join(dir,foundFile)))/float(1024),
				AEnums.MTIME : mtime,
				AEnums.VOLNAME : commDict[AEnums.NAME],
				AEnums.SERIAL : commDict[AEnums.SERIAL],
                AEnums.SETNAME : commDict[AEnums.SETNAME],
			}
			m = hashlib.md5()
			m.update(newFile[AEnums.NAME].encode('UTF-16'))
			m.update(newFile[AEnums.PATH].encode('UTF-16'))
			m.update(newFile[AEnums.VOLNAME])
			m.update(newFile[AEnums.SERIAL])
			id = m.hexdigest()
			newFile[AEnums.ID] = id
		if newFile:
			newFile[AEnums.PARENT] = fd[AEnums.ID]
			passedFiles.append(newFile)
	if not passedFiles and not root:
		return None
	filesIn.append(fd)
	[filesIn.append(x) for x in passedFiles if x not in filesIn]
	return fd

def main():
	Pyro.core.initServer()
	daemon = Pyro.core.Daemon(port=(port))
	uri=daemon.connect(indexServer(),'indexserver')
	print 'The daemon runs on port:',daemon.port
	print 'The object\'s uri is:',uri
	daemon.requestLoop()

if __name__ == "__main__":
	main()
